package com.heima.wemedia.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * @Author XHui
 * @Since 2024/2/14 18:15
 * @Version 1.0
 */
@Configuration
@Slf4j
public class RabbitMqConfig implements InitializingBean {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("初始化rabbitMQ配置");

        // 设置消息转换器，在进行发送消息时，会将消息序列化，转换为json格式
        // 若不设置，消息默认使用JDK的序列化，性能不太好
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());

        // 设置发送确认，回调方法 (当消息被rabbitmq接受到时，该方法会被执行)
        rabbitTemplate.setConfirmCallback(
                (correlationData, ack, cause) -> {
            if (!ack) {
                // TODO 可扩展自动重试机制
                log.error("发送消息到 mq 失败:{}", cause);
            }
        });

        // 设置消息返还 回调方法（当消息没有被正确路由到队列时，该方法会被执行）
        // 注意！！！当消息根据 路由key 可以路由到延迟队列时，可能会执行该回调方法
        // 因为若还没到触发时间，延迟交换机 会将先消息持久化到本地硬盘中，等到触发时机时，消息又被路由到延迟队列，
        rabbitTemplate.setReturnCallback(
                (message, replyCode, replyText, exchange, routingKey) -> {
                    Object headerOfDelay = message.getMessageProperties().getHeader("x-delay");
                    if(headerOfDelay != null){
                        return ;
                    }
                    log.error("消息返还回调触发 : 交换机:{} , 路由: {}, 消息内容: {}, 原因：{}",
                    exchange, routingKey, message, replyText);
        });
    }
}
